package logger

import (
	"fmt"
	"io"
	"log"
	"os"
	"runtime/debug"
)

var (
	config     *Config
	infoLogger *log.Logger
	errLogger  *log.Logger
)

type Config struct {
	Disable  bool
	Name     string
	Flag     int
	File     string
	InfoFile string
	ErrFile  string
	Level    int // Level xxx
	ShowLine bool
	Pad      int
}

func init() {
	config = &Config{
		Level: LevelAll, // default level
	}
	infoLogger = log.New(os.Stdout, "", 0)
	errLogger = log.New(os.Stderr, "", 0)
}

func Init(c *Config) (err error) {
	config = c

	// infoLogger.SetPrefix(config.Name)
	// errLogger.SetPrefix(config.Name)

	infoLogger.SetFlags(config.Flag)
	errLogger.SetFlags(config.Flag)

	var all *os.File
	if config.File != "" {
		all, err = os.OpenFile(config.File, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
		if err != nil {
			return
		}
	}

	if config.InfoFile != "" {
		f, err2 := os.OpenFile(config.InfoFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
		if err2 != nil {
			return err2
		}

		infoLogger.SetOutput(io.MultiWriter(f, os.Stdout, all))
	}

	if config.ErrFile != "" {
		f, err2 := os.OpenFile(config.ErrFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
		if err2 != nil {
			return err2
		}

		errLogger.SetOutput(io.MultiWriter(f, os.Stderr, all))
	}

	return nil
}

func InfofSkip(skip int, format string, v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelInfo {
		infoLogger.Printf(getBase(White("[INFO]"), skip)+White(format), v...)
	}
}

// Fatalf Fatalf
func Fatalf(format string, v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelFatal {
		errLogger.Fatalf(getBase(Red("[FATAL]"), 2)+Red(format)+fmt.Sprintf("\n%s", debug.Stack()), v...)
	}
}

// Fatal Fatal
func Fatal(v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelFatal {
		errLogger.Fatalf(getBase(Red("[FATAL]"), 2)+Red("%#v:(%s)")+fmt.Sprintf("\n%s", debug.Stack()), v, fmt.Sprint(v...))
	}
}

// Infof Infof alias of Printf
func Infof(format string, v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelInfo {
		infoLogger.Printf(getBase(White("[INFO]"), 2)+White(format), v...)
	}
}

// Info Info alias of Print
func Info(v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelInfo {
		infoLogger.Printf(getBase(White("[INFO]"), 2)+White("%#v:(%s)"), v, fmt.Sprint(v...))
	}
}

// InfoInterface 用于打印interface类型的参数，无法确定里面的值类型。
func InfoInterface(v ...interface{}) {
	if config.Disable {
		return
	}

	var args = []interface{}{getBase(White("[INFO]"), 2)}
	for _, item := range v {
		item = White(fmt.Sprint(item))
		args = append(args, item)
	}

	if config.Level >= LevelInfo {
		infoLogger.Print(args...)
	}
}

// Debugf Debugf
func Debugf(format string, v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelDebug {
		infoLogger.Printf(getBase(Cyan("[DEBUG]"), 2)+Cyan(format), v...)
	}
}

// Debug Debug
func Debug(v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelDebug {
		infoLogger.Printf(getBase(Cyan("[DEBUG]"), 2)+Cyan("%#v:(%s)"), v, fmt.Sprint(v...))
	}
}

// Warnf Warnf
func Warnf(format string, v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelWarn {
		infoLogger.Printf(getBase(Yellow("[WARN]"), 2)+Yellow(format), v...)
	}
}

// Warn Warn
func Warn(v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelWarn {
		infoLogger.Printf(getBase(Yellow("[WARN]"), 2)+Yellow("%#v:(%s)"), v, fmt.Sprint(v...))
	}
}

// Errorf Errorf
func Errorf(format string, v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelError {
		errLogger.Printf(getBase(Red("[ERROR]"), 2)+Red(format)+fmt.Sprintf("\n%s", debug.Stack()), v...)
	}
}

// Error Error
func Error(v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelError {
		errLogger.Printf(getBase(Red("[ERROR]"), 2)+Red("%#v:(%s)")+fmt.Sprintf("\n%s", debug.Stack()), v, fmt.Sprint(v...))
	}
}

// ErrorfNoStack ErrorfNoStack
func ErrorfNoStack(format string, v ...interface{}) {
	if config.Disable {
		return
	}

	if config.Level >= LevelError {
		errLogger.Printf(getBase(Red("[ERROR]"), 2)+Red(format), v...)
	}
}

// Printf, 传入什么打印什么，不会增加任何处理，比如文件，行号, 颜色等。
func Printf(s string, v ...interface{}) {
	if config.Disable {
		return
	}
	infoLogger.Printf(s, v...)
}

// Print, 传入什么打印什么，不会增加任何处理，比如文件，行号, 颜色等。
func Print(v ...interface{}) {
	if config.Disable {
		return
	}
	infoLogger.Print(v...)
}

// Use 使用一下变量，不会做任何事情，单纯为了避免变量未使用报错
func Use(v ...interface{}) {
}
